//
//  GameScene.m
//  DoodleDrop
//
//  Created by Tang HaiBo on 11-7-19.
//  Copyright 2011 Company. All rights reserved.
//

#import "GameScene.h"
#import "SimpleAudioEngine.h"

#define JIAN 0.4f
#define JIA 1.f
#define MAXSPEED 10.f

@interface GameScene () 

- (void)initSpiders;
- (void)resetSpiders;
- (void)runSpiderMoveSequence:(CCSprite*)spider;
- (void)checkForCollision;
- (void)runSpiderWiggleSequence:(CCSprite*)spider;
- (void)resetGame;
- (void)showGameOver;
@end


@implementation GameScene

+ (id)scene{
	CCScene *scene = [CCScene node];
	CCLayer *layer = [GameScene node];
	[scene addChild:layer];
	
	return scene;
}

- (id)init{
	if ((self = [super init]) ) {
		CCLOG(@"%@, %@", NSStringFromSelector(_cmd), self);
		self.isTouchEnabled = YES;
		_player = [CCSprite spriteWithFile:@"player.png"];
		[self addChild:_player z:0 tag:1];
		CGSize screenSize = [[CCDirector sharedDirector] winSize];
		float imgHeight = [_player texture].contentSize.height;
		_player.position = ccp(screenSize.width/2, imgHeight/2);
		
		[self scheduleUpdate];
		
		[self initSpiders];
		_scoreLabel = [CCLabelAtlas labelWithString:@"0" charMapFile:@"fps_images.png" itemWidth:16 itemHeight:24 startCharMap:'.'];
		_scoreLabel.position = CGPointMake(screenSize.width / 2, screenSize.height);
		_scoreLabel.anchorPoint = ccp(0.5f, 1.f);
		[_scoreLabel setScale:3.f];
		[self addChild:_scoreLabel z:-1 tag:3];
		
		[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"blues.mp3" loop:YES];
		[[SimpleAudioEngine sharedEngine] preloadEffect:@"alien-sfx.caf"];
		
		[self showGameOver];
	}
	
	return self;
}

- (void)dealloc{
	CCLOG(@"%@, %@", NSStringFromSelector(_cmd), self);
	[_spiders release];
	_spiders = nil;
	
	[[SimpleAudioEngine sharedEngine] unloadEffect:@"alien-sfx.caf"];
	[[SimpleAudioEngine sharedEngine] stopBackgroundMusic];
	[super dealloc];
}

#pragma mark 输入
-(void) registerWithTouchDispatcher
{
	[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:INT_MIN+1
											  swallowsTouches:YES];
}

-(CGPoint) locationFromTouch:(UITouch *)touch{
	CGPoint touchLocation = [touch locationInView: [touch view]]; 
	return [[CCDirector sharedDirector] convertToGL:touchLocation];
}


-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
	if (!_isGameOver) {
		_ptOld = [self locationFromTouch:touch];
	}else {
		[self resetGame];
	}
	
	return YES;
}
-(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
	CGPoint pt = [self locationFromTouch:touch];
	float offx = pt.x - _ptOld.x;
	//float offy = pt.y - _ptOld.y;
	_ptOld = pt;
	CCLOG(@"%@, (%.1f, %.1f)", NSStringFromSelector(_cmd), pt.x, pt.y);
	
	_playerVelocity.x = offx*JIA+offx*JIAN;
	
	if (_playerVelocity.x>MAXSPEED) {
		_playerVelocity.x = MAXSPEED;
	}
	
	if (_playerVelocity.x<-MAXSPEED) {
		_playerVelocity.x = -MAXSPEED;
	}
}

#pragma mark 更新
-(void) update:(ccTime)delta{
	CGSize screenSize = [[CCDirector sharedDirector] winSize];
	float imgWidth = [_player texture].contentSize.width;
	float leftLimit = imgWidth*0.5;
	float rightLimit = screenSize.width-imgWidth*0.5;
	
	CGPoint pt = _player.position;
	pt.x += _playerVelocity.x;
	if (pt.x>rightLimit) {
		pt.x = rightLimit;
	}
	
	if (pt.x<leftLimit) {
		pt.x = leftLimit;
	}
	_player.position = pt;
	
	[self checkForCollision];
	
	_totalTime += delta;
	int curScore =  (int)_totalTime;
	int score = [[_scoreLabel string] intValue];
	if (score<curScore) {
		[_scoreLabel setString:[NSString stringWithFormat:@"%d", curScore]];
	}
}

#pragma mark 蜘蛛
-(void) runSpiderWiggleSequence:(CCSprite*)spider{
	CCScaleTo *scaleUp = [CCScaleTo actionWithDuration:CCRANDOM_0_1()*2+1  scale:1.05f];
	CCEaseBackInOut *easeUp = [CCEaseBackInOut actionWithAction:scaleUp];
	CCScaleTo *scaleDown = [CCScaleTo actionWithDuration:CCRANDOM_0_1()*2+1 scale:0.95f];
	CCEaseBackInOut *easeDown = [CCEaseBackInOut actionWithAction:scaleDown];
	CCSequence *scaleSequence = [CCSequence actions:easeUp, easeDown, nil];
	CCRepeatForever *repeatScale = [CCRepeatForever actionWithAction:scaleSequence];
	[spider runAction:repeatScale];
}

- (void)initSpiders{
	CGSize screenSize = [[CCDirector sharedDirector] winSize];
	CCSprite *sprite = [CCSprite spriteWithFile:@"spider.png"];
	float imgWidth = sprite.contentSize.width;
	_numSpiderMoved = screenSize.width/imgWidth;
	
	_spiders = [[CCArray arrayWithCapacity:_numSpiderMoved] retain];
	for (int i=0; i<_numSpiderMoved; i++) {
		CCSprite *sprite = [CCSprite spriteWithFile:@"spider.png"];
		[self addChild:sprite z:0 tag:2];
		[_spiders addObject:sprite];
	}
	
	[self resetSpiders];
}

- (void)resetSpiders{
	CGSize screenSize = [[CCDirector sharedDirector] winSize];
	CCSprite *sprite = [CCSprite spriteWithFile:@"spider.png"];
	float imgWidth = sprite.contentSize.width;
	float imgheight = sprite.contentSize.height;
	
	float offsizeX = imgWidth*0.5f;
	float offsizeY = screenSize.height + imgheight*0.5f;
	for (int i=0; i<[_spiders count]; i++) {
		CCSprite *sprite = [_spiders objectAtIndex:i];
		sprite.position = ccp(offsizeX, offsizeY);
		
		offsizeX += imgWidth;
		
		[sprite stopAllActions];
	}
	
	[self unschedule:@selector(spidersUpdate:)];
	[self schedule:@selector(spidersUpdate:) interval:0.6f];
	
	_numSpiderMoved = 0;
	_spidersMoveDuration = 4.f;
}

-(void) spidersUpdate:(ccTime)delta{
	for (int i = 0; i < 10; i++) {
		int randomSpiderIndex = CCRANDOM_0_1() * [_spiders count];
		CCSprite* spider = [_spiders objectAtIndex:randomSpiderIndex];
		if ([spider numberOfRunningActions] == 0){
			[self runSpiderMoveSequence:spider];
			break;
		}
	}
}

- (void)runSpiderMoveSequence:(CCSprite*)spider{
	_numSpiderMoved++;
	if (_numSpiderMoved % 4 == 0 && _spidersMoveDuration > 1.0f) {
		_spidersMoveDuration -= 0.1f;
	}
	
	CGSize screenSize = [[CCDirector sharedDirector] winSize];
	CGPoint hangInTherePosition = CGPointMake(spider.position.x, screenSize.height - 3 * [spider texture].contentSize.height);
	CGPoint belowScreenPosition = CGPointMake(spider.position.x,
											  -[spider texture].contentSize.height);
	
	CCMoveTo* moveHang = [CCMoveTo actionWithDuration:4 position:hangInTherePosition];
	CCEaseElasticOut* easeHang = [CCEaseElasticOut actionWithAction:moveHang period:0.8f];
	CCMoveTo* moveEnd = [CCMoveTo actionWithDuration:_spidersMoveDuration position:belowScreenPosition];
	CCEaseBackInOut* easeEnd = [CCEaseBackInOut actionWithAction:moveEnd];
	
	CCCallFuncN *call = [CCCallFuncN actionWithTarget:self selector:@selector(spiderBelowScreen:)];
	CCSequence *sequence = [CCSequence actions:easeHang, easeEnd, call, nil];
	[spider runAction:sequence];
}

-(void) spiderBelowScreen:(id)sender{
	NSAssert([sender isKindOfClass:[CCSprite class]], @"sender is not a CCSprite!");
	CCSprite* spider = (CCSprite*)sender;
	
	CGPoint pos = spider.position; CGSize screenSize = [[CCDirector sharedDirector] winSize]; pos.y = screenSize.height + [spider texture].contentSize.height; 
	spider.position = pos;
}

#pragma mark 碰撞检测
-(void) checkForCollision{
	float playerImageSize = [[_player texture] contentSize].width;
	float spriderImageSize = [[[_spiders lastObject] texture] contentSize].width;
	
	float playerCollisionRadius = playerImageSize * 0.4f; 
	float spiderCollisionRadius = spriderImageSize * 0.4f;
	
	float maxCollisionDistance = playerCollisionRadius + spiderCollisionRadius;
	
	int numSpiders = [_spiders count];
	for (int i=0; i<numSpiders; i++) {
		CCSprite *spider = [_spiders objectAtIndex:i];
		if ([spider numberOfRunningActions]==0) {
			continue;
		}
		
		float actualDistance = ccpDistance(_player.position, spider.position);
		if (actualDistance<maxCollisionDistance) {
			[self showGameOver];
			
			[[SimpleAudioEngine sharedEngine] playEffect:@"alien-sfx.caf"];
		}
	}
}



-(void) draw
{
	
	#if DEBUG
	// Iterate through all nodes of the layer.
	for (CCNode* node in [self children])
	{
		// Make sure the node is a CCSprite and has the right tags.
		if ([node isKindOfClass:[CCSprite class]] && (node.tag == 1 || node.tag == 2))
		{
			// The sprite's collision radius is a percentage of its image width. Use that to draw a circle
			// which represents the sprite's collision radius.
			CCSprite* sprite = (CCSprite*)node;
			float radius = [sprite texture].contentSize.width * 0.4f;
			float angle = 0;
			int numSegments = 10;
			bool drawLineToCenter = NO;
			ccDrawCircle(sprite.position, radius, angle, numSegments, drawLineToCenter);
		}
	}
	#endif
	
	CGSize screenSize = [[CCDirector sharedDirector] winSize];
	
	// always keep variables you have to calculate only once outside the loop
	float threadCutPosition = screenSize.height * 0.75f;
	
	// Draw a spider thread using OpenGL
	// CCARRAY_FOREACH is a bit faster than regular for loop
	CCSprite* spider;
	CCARRAY_FOREACH(_spiders, spider)
	{
		// only draw thread up to a certain point
		if (spider.position.y > threadCutPosition)
		{
			// vary thread position a little so it looks a bit more dynamic
			float threadX = spider.position.x + (CCRANDOM_0_1() * 2.0f - 1.0f);
			
			glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
			ccDrawLine(spider.position, CGPointMake(threadX, screenSize.height));
		}
	}
}

#pragma mark 游戏结束
-(void) showGameOver
{	
	_isGameOver = YES;
	// have everything stop
	CCNode* node;
	CCARRAY_FOREACH([self children], node)
	{
		[node stopAllActions];
	}
	
	// I do want the spiders to keep wiggling so I simply restart this here
	CCSprite* spider;
	CCARRAY_FOREACH(_spiders, spider)
	{
		[self runSpiderWiggleSequence:spider];
	}
	
	// disable accelerometer input for the time being
	self.isAccelerometerEnabled = NO;
	// but allow touch input now
	self.isTouchEnabled = YES;
	
	// stop the scheduled selectors
	[self unscheduleAllSelectors];
	
	// add the labels shown during game over
	CGSize screenSize = [[CCDirector sharedDirector] winSize];
	
	CCLabelTTF* gameOver = [CCLabelTTF labelWithString:@"GAME OVER!" fontName:@"Marker Felt" fontSize:60];
	gameOver.position = CGPointMake(screenSize.width / 2, screenSize.height / 3);
	[self addChild:gameOver z:100 tag:100];
	
	// game over label runs 3 different actions at the same time to create the combined effect
	// 1) color tinting
	CCTintTo* tint1 = [CCTintTo actionWithDuration:2 red:255 green:0 blue:0];
	CCTintTo* tint2 = [CCTintTo actionWithDuration:2 red:255 green:255 blue:0];
	CCTintTo* tint3 = [CCTintTo actionWithDuration:2 red:0 green:255 blue:0];
	CCTintTo* tint4 = [CCTintTo actionWithDuration:2 red:0 green:255 blue:255];
	CCTintTo* tint5 = [CCTintTo actionWithDuration:2 red:0 green:0 blue:255];
	CCTintTo* tint6 = [CCTintTo actionWithDuration:2 red:255 green:0 blue:255];
	CCSequence* tintSequence = [CCSequence actions:tint1, tint2, tint3, tint4, tint5, tint6, nil];
	CCRepeatForever* repeatTint = [CCRepeatForever actionWithAction:tintSequence];
	[gameOver runAction:repeatTint];
	
	// 2) rotation with ease
	CCRotateTo* rotate1 = [CCRotateTo actionWithDuration:2 angle:3];
	CCEaseBounceInOut* bounce1 = [CCEaseBounceInOut actionWithAction:rotate1];
	CCRotateTo* rotate2 = [CCRotateTo actionWithDuration:2 angle:-3];
	CCEaseBounceInOut* bounce2 = [CCEaseBounceInOut actionWithAction:rotate2];
	CCSequence* rotateSequence = [CCSequence actions:bounce1, bounce2, nil];
	CCRepeatForever* repeatBounce = [CCRepeatForever actionWithAction:rotateSequence];
	[gameOver runAction:repeatBounce];
	
	// 3) jumping
	CCJumpBy* jump = [CCJumpBy actionWithDuration:3 position:CGPointZero height:screenSize.height / 3 jumps:1];
	CCRepeatForever* repeatJump = [CCRepeatForever actionWithAction:jump];
	[gameOver runAction:repeatJump];
	
	// touch to continue label
	CCLabelTTF* touch = [CCLabelTTF labelWithString:@"tap screen to play again" fontName:@"Arial" fontSize:20];
	touch.position = CGPointMake(screenSize.width / 2, screenSize.height / 4);
	[self addChild:touch z:100 tag:101];
	
	// did you try turning it off and on again?
	CCBlink* blink = [CCBlink actionWithDuration:10 blinks:20];
	CCRepeatForever* repeatBlink = [CCRepeatForever actionWithAction:blink];
	[touch runAction:repeatBlink];
}

- (void)resetGame
{
	
	// remove game over label & touch to continue label
	[self removeChildByTag:100 cleanup:YES];
	[self removeChildByTag:101 cleanup:YES];
	
	// re-enable accelerometer
	self.isTouchEnabled = YES;
	
	// re-schedule update
	[self scheduleUpdate];
	
	// reset score
	[self resetSpiders];
	//初始化数值
	[_scoreLabel setString:@"0"];
	_totalTime = 0.f;
	
	_isGameOver = NO;
}
@end
